package com.srit.recipes.service.impl;

import com.srit.recipes.common.exception.RecipesException;
import com.srit.recipes.common.parent.DaoInject;
import com.srit.recipes.entity.*;
import com.srit.recipes.service.BaseService;
import com.srit.recipes.service.RecipesAnalysis;
import com.srit.recipes.vo.DailyCostBean;
import com.srit.recipes.vo.RecipesNutritionBean;
import com.srit.recipes.vo.RecipesOverviewIngredient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class RecipesAnalysisImpl extends DaoInject implements RecipesAnalysis {
    @Autowired
    private BaseService baseService;

    @Autowired
    private ProcurementServiceImpl procurementService;

    @Override
    public Object recipesNutritionAnalysis(Integer id, int type) {

        WeekRecipes weekRecipes = weekRecipesDao.getById(id);

        List<WeekRecipesDetail> recipesDetails = weekRecipesDetailDao.findAllByWeekRecipesId(id);
        Function<WeekRecipesDetail, String> keyMapper;

        switch (type) {
            case 0:
                keyMapper = recipesDetail -> "";
                break;
            case 1:
                keyMapper = recipesDetail -> String.valueOf(recipesDetail.getWeek());
                break;
            default:
                keyMapper = recipesDetail -> "";
        }

        Map<String, List<WeekRecipesDetail>> groups = recipesDetails.stream().collect(Collectors.groupingBy(keyMapper, Collectors.toList()));


//        Set<String> ids = recipesDetails.stream().map(WeekRecipesDetail::getRecipesId).collect(Collectors.toSet());
//        Map<String, RecipesNutrition> nutritionMap = recipesNutritionDao.findAllByCpIdIn(ids).stream().collect(Collectors.toMap(RecipesNutrition::getCpId, Function.identity()));

        List<RecipesNutritionBean> nutritionBeans = new ArrayList<>();

        NutritionStandard standard = nutritionStandardDao.findByRYXLAndType(weekRecipes.getPerType(), weekRecipes.getType());

        groups.forEach((x, y) -> {
            RecipesNutritionBean nutritionBean = new RecipesNutritionBean();
            for (WeekRecipesDetail recipesDetail : y) {
                RecipesNutrition recipesNutrition = recipesNutritionMap.get(recipesDetail.getRecipesId());
                if (recipesNutrition != null) {
                    nutritionBean.setDBZ(addString(nutritionBean.getDBZ(), recipesNutrition.getDBZ(), recipesDetail.getRate()));
                    nutritionBean.setWA(addString(nutritionBean.getWA(), recipesNutrition.getWA(), recipesDetail.getRate()));
                    nutritionBean.setXIN(addString(nutritionBean.getXIN(), recipesNutrition.getXIN(), recipesDetail.getRate()));
                    nutritionBean.setZF(addString(nutritionBean.getZF(), recipesNutrition.getZF(), recipesDetail.getRate()));
                    nutritionBean.setWE(addString(nutritionBean.getWE(), recipesNutrition.getWE(), recipesDetail.getRate()));
                    nutritionBean.setWC(addString(nutritionBean.getWC(), recipesNutrition.getWC(), recipesDetail.getRate()));
                    nutritionBean.setXI(addString(nutritionBean.getXI(), recipesNutrition.getXI(), recipesDetail.getRate()));
                    nutritionBean.setTL(addString(nutritionBean.getTL(), recipesNutrition.getTL(), recipesDetail.getRate()));
                    nutritionBean.setWB1(addString(nutritionBean.getWB1(), recipesNutrition.getWB1(), recipesDetail.getRate()));
                    nutritionBean.setGAI(addString(nutritionBean.getGAI(), recipesNutrition.getGAI(), recipesDetail.getRate()));
                    nutritionBean.setNL(addString(nutritionBean.getNL(), recipesNutrition.getNL(), recipesDetail.getRate()));
                    nutritionBean.setWB2(addString(nutritionBean.getWB2(), recipesNutrition.getWB2(), recipesDetail.getRate()));
                    nutritionBean.setTIE(addString(nutritionBean.getTIE(), recipesNutrition.getTIE(), recipesDetail.getRate()));
                    nutritionBean.setDGC(addString(nutritionBean.getDGC(), recipesNutrition.getDGC(), recipesDetail.getRate()));
                    nutritionBean.setDWXDB(addString(nutritionBean.getDWXDB(), recipesNutrition.getDWXDB(), recipesDetail.getRate()));
                    nutritionBean.setDDDB(addString(nutritionBean.getDDDB(), recipesNutrition.getDDDB(), recipesDetail.getRate()));
                    nutritionBean.setDWXZF(addString(nutritionBean.getDWXZF(), recipesNutrition.getDWXZF(), recipesDetail.getRate()));
                    nutritionBean.setZTNL(addString(nutritionBean.getZTNL(), recipesNutrition.getZTNL(), recipesDetail.getRate()));
                    nutritionBean.setDWXWA(addString(nutritionBean.getDWXWA(), recipesNutrition.getDWXWA(), recipesDetail.getRate()));

                    nutritionBean.setGroup(x);
                }
            }
            nutritionBeans.add(nutritionBean);
        });

        Map<String, Object> analysisMap = new HashMap<>();
        analysisMap.put("recipesNutrition", nutritionBeans);
        analysisMap.put("recipesStandard", standard);


        return analysisMap;
    }

    @Override
    public Collection<RecipesOverviewIngredient> recipesIngredientAnalysis(Integer id) {
        WeekRecipes weekRecipes = weekRecipesDao.getById(id);
        int perNum = weekRecipes.getPerNum();

        List<WeekRecipesDetail> recipesDetails = weekRecipesDetailDao.findAllByWeekRecipesId(id);

        Map<String, RecipesOverviewIngredient> ingredientMap = calculateWithSc(recipesDetails, baseService, perNum);


        return ingredientMap.values();
    }


    private String addString(String a, String b, float rate) {

        StringBuilder x = new StringBuilder("0");
        StringBuilder y = new StringBuilder("0");
        StringBuilder unit = new StringBuilder();
        if (a != null) {
            for (char c : a.toCharArray()) {
                if (Character.isDigit(c) || c == '.') {
                    x.append(c);
                } else {
                    break;
                }
            }
        }

        if (b != null) {
            for (char c : b.toCharArray()) {
                if (Character.isDigit(c) || c == '.') {
                    y.append(c);
                } else {
                    unit.append(c);
                }
            }
        }

        BigDecimal add = new BigDecimal(x.toString()).add(new BigDecimal(y.toString()).multiply(new BigDecimal(Float.toString(rate))));
        return add.toString() + unit;

    }

    @Override
    public Object recipesCost(Integer id) {

        WeekRecipes weekRecipes = weekRecipesDao.getById(id);

//        if (weekRecipes.getProcurementState() != WeekRecipes.EXAMINE_PASS) {
//            throw RecipesException.of("采购单审核未通过");
//        }
        List<ProcurementDetailInfo> procurementDetailInfos = procurementDetailDao.findAllByRecipesId(id);
        if (CollectionUtils.isEmpty(procurementDetailInfos)) {
            throw RecipesException.of("未找到采购记录");
        }
        procurementService.addExtra(procurementDetailInfos);

        Map<Integer, List<ProcurementDetailInfo>> weekProcurementMap = procurementDetailInfos.stream().collect(Collectors.groupingBy(ProcurementDetailInfo::getWeek));

        List<DailyCostBean> dailyCostBeans = new ArrayList<>();
        for (Map.Entry<Integer, List<ProcurementDetailInfo>> entry : weekProcurementMap.entrySet()) {
            DailyCostBean dailyCostBean = new DailyCostBean();
            dailyCostBean.setWeek(entry.getKey());
            dailyCostBean.setTotalCost(entry.getValue().stream().map(x -> {
                Double price = x.getPrice();
                if (price == null) {
                    return 0d;
                }
                return Math.max(0, (x.getWight()) * price / 1000);
            }).reduce(0d, Double::sum));
            dailyCostBeans.add(dailyCostBean);
        }

        return dailyCostBeans;
    }


    public static Map<String, RecipesOverviewIngredient> calculateWithSc(List<WeekRecipesDetail> recipesDetails, BaseService baseService, int perNum) {
        Map<String, RecipesOverviewIngredient> ingredientMap = new HashMap<>();

        for (WeekRecipesDetail recipesDetail : recipesDetails) {
            List<IngredientInfo> ingredientInfos = baseService.recipesIngredient(recipesDetail.getRecipesId());

            for (IngredientInfo ingredientInfo : ingredientInfos) {
                RecipesOverviewIngredient recipesOverviewIngredient = ingredientMap.computeIfAbsent(ingredientInfo.getScName(), s -> new RecipesOverviewIngredient());
                recipesOverviewIngredient.setName(ingredientInfo.getScName());
                recipesOverviewIngredient.setWight(recipesOverviewIngredient.getWight() + ingredientInfo.getPortion() * perNum / 100);
                recipesOverviewIngredient.setUnit(ingredientInfo.getUnit());
            }

        }
        return ingredientMap;
    }
}
